import json

from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from django import http
from django.views import View

from apps.contents.utils import get_categories
from apps.goods.models import *
from apps.orders.models import OrderInfo, OrderGoods
from meiduo_mall.settings.dev import LOGGER
from utils.response_code import RETCODE
from .utils import *
from django.core.paginator import Paginator, EmptyPage


# Create your views here.


class ListView(View):
    def get(self, request, category_id, page_num):
        """商品列表页面"""
        # 判断 category_id 是否正确
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsChannel.DoesNotExist as e:
            return http.HttpResponseNotFound('GoodsCategory does not exist')

        # 查询商品频道分类
        categories = get_categories()
        # 面包屑导航
        breadcrumb = get_breadcrumb(category)

        # 接收sort参数：如果用户不传，就是默认的排序规则
        sort = request.GET.get('sort', 'default')
        # 按照排序规则查询该分类商品SKU信息
        if sort == 'price':
            # 按照价格由低到高
            sort_field = 'price'
        elif sort == 'hot':
            # 按照销量由高到低
            sort_field = '-sales'
        else:
            # 'price'和'sales'以外的所有排序方式都归为'default'
            sort_field = 'create_time'
        # 查询当前类并上架的商品按照规定的排序方式进行排序
        skus = SKU.objects.filter(category=category, is_launched=True).order_by(sort_field)

        # 分页器 参数一:数据, 参数二:分几页
        paginator = Paginator(skus, 5)
        # 获取每页商品数据
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            # 如果page_num不正确，默认给用户404
            return http.HttpResponseNotFound('empty page')
        # 获取列表页总页数
        total_page = paginator.num_pages
        context = {
            "categories": categories,
            "breadcrumb": breadcrumb,
            'sort': sort,  # 排序字段
            'category': category,  # 第三级分类
            'page_skus': page_skus,  # 分页后数据
            'total_page': total_page,  # 总页数
            'page_num': page_num,  # 当前页码
        }
        return render(request, "list.html", context)


class HottView(View):
    def get(self, request, category_id):
        """商品热销榜"""
        skus = SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]

        # 序列化
        hot_skus = []
        for sku in skus:
            hot_skus.append({
                'id': sku.id,
                'default_image_url': sku.default_image.url,
                'name': sku.name,
                'price': sku.price
            })
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': hot_skus})


class DetailView(View):
    def get(self, request, sku_id):
        """商品详情页"""
        # 获取当前sku的信息
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return render(request, '404.html')

        # 查询商品频道分类
        categories = get_categories()
        # 查询面包屑导航
        breadcrumb = get_breadcrumb(sku.category)

        # 构建当前商品的规格键 一个商品对应多个规格
        sku_specs = sku.specs.order_by('spec_id')
        sku_key = []
        for spec in sku_specs:
            sku_key.append(spec.option.id)
        # 获取当前商品的所有SKU
        skus = sku.spu.sku_set.all()
        # 构建不同规格参数（选项）的sku字典
        spec_sku_map = {}
        for s in skus:
            # 获取sku的规格参数
            s_specs = s.specs.order_by('spec_id')
            # 用于形成规格参数-sku字典的键
            key = []
            for spec in s_specs:
                key.append(spec.option.id)
            # 向规格参数-sku字典添加记录
            spec_sku_map[tuple(key)] = s.id
        # 获取当前商品的规格信息
        goods_specs = sku.spu.specs.order_by('id')
        # 若当前sku的规格信息不完整，则不再继续
        if len(sku_key) < len(goods_specs):
            return
        for index, spec in enumerate(goods_specs):
            # 复制当前sku的规格键
            key = sku_key[:]
            # 该规格的选项
            spec_options = spec.options.all()
            for option in spec_options:
                # 在规格参数sku字典中查找符合当前规格的sku
                key[index] = option.id
                option.sku_id = spec_sku_map.get(tuple(key))
            spec.spec_options = spec_options

        # 渲染页面
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'sku': sku,
            'specs': goods_specs,
        }
        return render(request, 'detail.html', context)


class DetailVisitView(View):
    """详情页分类商品访问量"""

    def post(self, request, category_id):
        try:
            # 1.获取当前商品
            category = GoodsCategory.objects.get(id=category_id)
        except Exception as e:
            return http.HttpResponseNotFound('缺少必传参数')

        # 2.查询日期数据
        from datetime import datetime
        # 将日期按照格式转换成字符串
        today_str = datetime.now().strftime('%Y-%m-%d')
        # 将字符串再转换成日期格式
        today_date = datetime.strptime(today_str, '%Y-%m-%d')

        from apps.goods.models import GoodsVisitCount
        try:
            # 3.如果有当天商品分类的数据  就累加数量
            count_data = category.goodsvisitcount_set.get(date=today_date)
        except:
            # 4. 没有, 就新建之后在增加
            count_data = GoodsVisitCount()

        try:
            count_data.count += 1
            count_data.category = category
            count_data.save()
        except Exception as e:
            return http.HttpResponseServerError('新增失败')

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


class OrderShowView(LoginRequiredMixin, View):
    def get(self, request, page_num):
        user = request.user
        # 查询当前用户所有订单
        # order1 = OrderInfo.objects.filter(user_id=user.id).order_by("-create_time")
        orders = user.orderinfo_set.all().order_by("-create_time")

        # 将数据分页
        paginator = Paginator(orders, 3)
        # 获取当前页的数据
        page = paginator.page(page_num)
        # 遍历订单 OrderInfo
        page_list = []
        for order in page:
            order_dict = {}
            order_dict["create_time"] = order.create_time.strftime('%Y-%m-%d %H:%M:%S')
            order_dict["order_id"] = order.order_id
            order_dict["details"] = []
            order_dict["freight"] = order.freight
            order_dict["status"] = order.status
            detail_dict = {}
            for good in order.skus.all():
                detail_dict["count"] = good.count
                detail_dict["price"] = good.price
                detail_dict["name"] = good.sku.name
                detail_dict["default_image_url"] = good.sku.default_image.url
                detail_dict["total_amount"] = good.count * good.price   # + order.freight
                order_dict["details"].append(detail_dict)
                order_dict["total_amount"] = good.count * good.price + order.freight
                page_list.append(order_dict)
        print(page_list[0]["status"])
        context = {
            "page": page_list,
            'total_page': paginator.num_pages,  # 总页数
            'page_num': page_num,  # 当前页码
        }

        return render(request, "user_center_order.html", context)


class GetOrderView(LoginRequiredMixin, View):
    def get(self, request):
        page = request.GET.get("page")
        page_size = request.GET.get("page_size")
        return http.JsonResponse({})


class CommentView(LoginRequiredMixin, View):
    def get(self, request):
        # 接收订单编号
        order_id = request.GET.get('order_id')

        # 查询订单商品列表
        try:
            order = OrderInfo.objects.get(pk=order_id, user_id=request.user.id)
        except:
            return http.Http404('商品编号无效')

        # 获取订单的所有商品
        skus = []
        # 筛选该订单号没有评价的订单
        for detail in order.skus.filter(is_commented=False):
            skus.append({
                'sku_id': detail.sku.id,
                'default_image_url': detail.sku.default_image.url,
                'name': detail.sku.name,
                'price': str(detail.price),
                'order_id': order_id,
                'comment': detail.comment,
                'score': detail.score,
                'is_anonymous': str(detail.is_anonymous),
            })
        context = {
            'skus': skus
        }
        return render(request, 'goods_judge.html', context)


class PutCommentView(LoginRequiredMixin, View):
    def post(self, request, order_id):
        """订单评价"""
        json_dict = json.loads(request.body.decode())
        print(json_dict)
        order_id = json_dict.get('order')
        sku_id = json_dict.get('sku')
        score = json_dict.get('score')
        comment = json_dict.get('comment')
        is_anonymous = json_dict.get('is_anonymous')
        if is_anonymous == "False":
            is_anonymous = False
        elif is_anonymous == "True":
            is_anonymous = True

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('参数sku_id错误')
        try:
            OrderGoods.objects.filter(order_id=order_id, sku_id=sku_id, is_commented=False)\
                .update(comment=comment, score=score, is_anonymous=is_anonymous, is_commented=True)
            # print(order_good)
        except:
            return http.HttpResponseForbidden('商品数据查询出错')

        # 累计评论数据
        sku.comments += 1
        sku.save()
        sku.spu.comments += 1
        sku.spu.save()
        # 如果所有订单商品都已评价，则修改订单状态为已完成
        if OrderGoods.objects.filter(order_id=order_id, is_commented=False).count() == 0:
            OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['FINISHED'])
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '评价成功'})


class CommentSKUView(LoginRequiredMixin, View):
    def get(self, request, sku_id):
        # 查询指定sku_id的所有评论信息
        comments = OrderGoods.objects.filter(sku_id=sku_id, is_commented=True)
        comment_list = []
        # detail表示OrderGoods对象
        for detail in comments:
            username = detail.order.user.username
            if detail.is_anonymous:
                username = '******'
            comment_list.append({
                'username': username,
                'comment': detail.comment,
                'score': detail.score
            })

        return http.JsonResponse({
            'code': RETCODE.OK,
            'errmsg': "OK",
            'goods_comment_list': comment_list
        })
